﻿
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using TNCGameEngine.Content;

namespace TNCGameEngine.Graphics
{

    /// <summary>
    /// Defines a sprite represnts an image in 2D screen coordinates.
    /// </summary>
    public class Sprite
    {

        #region "Properties"

        private int width = 0;
        /// <summary>
        /// Width of the sprite.
        /// </summary>
        /// <remarks>Gets the width of the image in pixels.</remarks>
        /// <value>0</value>
        public int Width
        {
            get { return this.width; }
        }

        private int height = 0;
        /// <summary>
        /// Height of the sprite.
        /// </summary>
        /// <remarks>Gets the height of the image in pixels.</remarks>
        /// <value>0</value>
        public int Height
        {
            get { return this.height; }
        }

        private Texture2D image = null;
        /// <summary>
        /// Image that is displayed when drawn on screen.
        /// </summary>
        /// <remarks>Gets the image if already loaded, otherwise null.</remarks>
        public Texture2D Image
        {
            get { return this.image; }
        }

        /// <summary>
        /// Checks if the image has already been loaded properly.
        /// </summary>
        /// Gets the Boolean value of the state of the image.
        public bool IsImageLoaded
        {
            get { return (this.image != null); }
        }

        private Color tint = Color.White;
        /// <summary>
        /// Color used to tint the image when drawn onto screen.
        /// </summary>
        /// Use Color.White for full color and no tinting (set by default).
        /// <value>Color.White</value>
        public Color Tint
        {
            get { return this.tint; }
            set { this.tint = value; }
        }

        #endregion

        #region "Constructors"

        /// <summary>
        /// Generates a new Sprite.
        /// </summary>
        /// <remarks>A 2D image to be used in screen cordinates.</remarks>
        public Sprite()
        {
            // do nothing
        }

        /// <summary>
        /// Generates a new Sprite and loads the specified image file.
        /// </summary>
        /// <param name="content">The content manger.</param>
        /// <param name="file">Image file to be loaded.</param>
        /// <remarks>A 2D image to be used in screen cordinates.</remarks>
        public Sprite(SharedContentManager content, string file)
            : this()
        {
            this.LoadImage(content, file);
        }

        /// <summary>
        /// Generates a new Sprite and loads the specified image file.
        /// </summary>
        /// <param name="loader">The content loader.</param>
        /// <param name="file">Image file to be loaded.</param>
        /// <remarks>A 2D image to be used in screen cordinates.</remarks>
        public Sprite(ContentLoader loader, string file)
            : this()
        {
            this.LoadImage(loader.Content, file);
        }

        #endregion

        #region "Methods"

        /// <summary>
        /// Loads the specified image.
        /// </summary>
        /// <param name="content">Content manager.</param>
        /// <param name="file">The path of the file to be loaded.</param>
        /// <returns>A boolean value indicating the loading was successful or not.</returns>
        public bool LoadImage(SharedContentManager content, string file)
        {

            // unload the already loaded image
            if (this.IsImageLoaded)
            {
                content.UnloadSingleContent(this.image);
            }

            // load the new image
            this.image = content.Load<Texture2D>(file);

            if (this.IsImageLoaded)
            {
                // set new width and height values
                this.width = this.image.Width;
                this.height = this.image.Height;
                return true;
            }
            else
            {
                return false;
            }

        }

        /// <summary>
        /// Draws the image into the specified rectangle in screen coordinates.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch associated with the current frame.</param>
        /// <param name="rectangle">The rectanlge that specifies the destination area on the screen.</param>
        public void Draw(SpriteBatch spriteBatch, Rectangle rectangle)
        {
            if (!this.IsImageLoaded) { return; }
            spriteBatch.Draw(this.image, rectangle, this.tint);
        }

        /// <summary>
        /// Draws the image with the speficied scale having the top-left corner as the specified location.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch associated with the current frame.</param>
        /// <param name="location">The top-left corner on the image in screen corrdinates (pixels).</param>
        /// <param name="scale">The magnitude of scaling in the X and Y directions.</param>
        public void Draw(SpriteBatch spriteBatch, Vector2 location, Vector2 scale)
        {
            this.Draw(spriteBatch, new Rectangle((int)location.X, (int)location.Y, (int)(scale.X * this.width), (int)(scale.Y * this.height)));
        }

        /// <summary>
        /// Draws the image having the top-left corner as the specified location; image not scaled.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch associated with the current frame.</param>
        /// <param name="location">The top-left corner on the image in screen corrdinates (pixels).</param>
        public void Draw(SpriteBatch spriteBatch, Vector2 location)
        {
            this.Draw(spriteBatch, location, Vector2.One);
        }

        /// <summary>
        /// Draws the image with the speficied scale, centered at the specified location.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch associated with the current frame.</param>
        /// <param name="center">The center the image in screen corrdinates (pixels).</param>
        /// <param name="scale">The magnitude of scaling in the X and Y directions.</param>
        public void DrawCentered(SpriteBatch spriteBatch, Vector2 center, Vector2 scale)
        {
            float w = scale.X * this.width;
            float h = scale.Y * this.height;
            this.Draw(spriteBatch, new Rectangle((int)(center.X - w / 2), (int)(center.Y - h / 2), (int)w, (int)h));
        }

        /// <summary>
        /// Draws the image centered at the specified location; image not scaled.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch associated with the current frame.</param>
        /// <param name="center">The center of the image in screen corrdinates (pixels).</param>
        public void DrawCentered(SpriteBatch spriteBatch, Vector2 center)
        {
            this.DrawCentered(spriteBatch, center, Vector2.One);
        }

        #endregion

    }

}
